﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;

namespace Tank
{
	public enum SoundType
	{
		TANK_ENGINE_1,
		TANK_ENGINE_2,
		TANK_ENGINE_3,
		TANK_TURRET,
		TANK_FIRE_1,
		TANK_FIRE_2,
		TANK_FIRE_3,
		TANK_DAMAGE_1,
		TANK_DAMAGE_2,
		TANK_EXPLODE,
        BUTTON_CLICK,
        SONG_TITLE,
        SONG_RESULTS,
        TANK_BOOST,
	}
	public class SoundManager
	{
		private static volatile SoundManager instance;
		private static object syncRoot = new Object();

		Dictionary<SoundType, SoundEffect> sounds;
		Dictionary<SoundType, SoundEffectInstance> soundInst;
		Dictionary<PlayerIndex, Dictionary<SoundType, SoundEffectInstance>> playerSounds;

		Random random;
		ContentManager _content;

		public static SoundManager Instance
		{
			get
			{
				if (instance == null)
				{
					lock (syncRoot)
					{
						if (instance == null)
							instance = new SoundManager();
					}
				}
				return instance;
			}
		}
		public Random Random
		{
			get { return random; }
		}

		//=============================================================
		// InitSounds
		// Desc: Loads all music and sound effects into ContentManager
		//=============================================================
		public void InitSounds(ContentManager Content)
		{
			_content = Content;
			random = new Random();
			sounds = new Dictionary<SoundType, SoundEffect>();

			sounds.Add(SoundType.TANK_ENGINE_1, Content.Load<SoundEffect>("Audio/engine_1"));
			sounds.Add(SoundType.TANK_ENGINE_2, Content.Load<SoundEffect>("Audio/engine_2"));
			sounds.Add(SoundType.TANK_ENGINE_3, Content.Load<SoundEffect>("Audio/engine_3"));
			sounds.Add(SoundType.TANK_TURRET, Content.Load<SoundEffect>("Audio/turret"));
			sounds.Add(SoundType.TANK_FIRE_1, Content.Load<SoundEffect>("Audio/fire_1"));
			sounds.Add(SoundType.TANK_FIRE_2, Content.Load<SoundEffect>("Audio/fire_2"));
			sounds.Add(SoundType.TANK_FIRE_3, Content.Load<SoundEffect>("Audio/fire_3"));
			sounds.Add(SoundType.TANK_DAMAGE_1, Content.Load<SoundEffect>("Audio/damage_1"));
			sounds.Add(SoundType.TANK_DAMAGE_2, Content.Load<SoundEffect>("Audio/damage_2"));
			sounds.Add(SoundType.TANK_EXPLODE, Content.Load<SoundEffect>("Audio/explosion"));
            sounds.Add(SoundType.BUTTON_CLICK, Content.Load<SoundEffect>("Audio/click"));
            sounds.Add(SoundType.SONG_TITLE, Content.Load<SoundEffect>("Audio/song_title"));
            sounds.Add(SoundType.TANK_BOOST, Content.Load<SoundEffect>("Audio/leeroy_jenkins"));
            sounds.Add(SoundType.SONG_RESULTS, Content.Load<SoundEffect>("Audio/songresult"));

			
			soundInst = new Dictionary<SoundType, SoundEffectInstance>();

			soundInst.Add(SoundType.TANK_ENGINE_1, sounds[SoundType.TANK_ENGINE_1].CreateInstance());
			soundInst.Add(SoundType.TANK_ENGINE_2, sounds[SoundType.TANK_ENGINE_2].CreateInstance());
			soundInst.Add(SoundType.TANK_ENGINE_3, sounds[SoundType.TANK_ENGINE_3].CreateInstance());
			soundInst.Add(SoundType.TANK_TURRET, sounds[SoundType.TANK_TURRET].CreateInstance());
			soundInst.Add(SoundType.TANK_FIRE_1, sounds[SoundType.TANK_FIRE_1].CreateInstance());
			soundInst.Add(SoundType.TANK_FIRE_2, sounds[SoundType.TANK_FIRE_2].CreateInstance());
			soundInst.Add(SoundType.TANK_FIRE_3, sounds[SoundType.TANK_FIRE_3].CreateInstance());
			soundInst.Add(SoundType.TANK_DAMAGE_1, sounds[SoundType.TANK_DAMAGE_1].CreateInstance());
			soundInst.Add(SoundType.TANK_DAMAGE_2, sounds[SoundType.TANK_DAMAGE_2].CreateInstance());
			soundInst.Add(SoundType.TANK_EXPLODE, sounds[SoundType.TANK_EXPLODE].CreateInstance());
            soundInst.Add(SoundType.BUTTON_CLICK, sounds[SoundType.BUTTON_CLICK].CreateInstance());
            soundInst.Add(SoundType.SONG_TITLE, sounds[SoundType.SONG_TITLE].CreateInstance());
            soundInst.Add(SoundType.SONG_RESULTS, sounds[SoundType.SONG_RESULTS].CreateInstance());
            soundInst.Add(SoundType.TANK_BOOST, sounds[SoundType.TANK_BOOST].CreateInstance());

			soundInst[SoundType.TANK_ENGINE_1].IsLooped = true;
			soundInst[SoundType.TANK_ENGINE_2].IsLooped = true;
			soundInst[SoundType.TANK_ENGINE_3].IsLooped = true;
			soundInst[SoundType.SONG_TITLE].IsLooped = true;
			//soundInst[SoundType.TANK_TURRET].IsLooped = true;

			playerSounds = new Dictionary<PlayerIndex,Dictionary<SoundType,SoundEffectInstance>>();
			playerSounds.Add(PlayerIndex.One, soundInst);
			playerSounds.Add(PlayerIndex.Two, soundInst);
			playerSounds.Add(PlayerIndex.Three, soundInst);
			playerSounds.Add(PlayerIndex.Four, soundInst);
			

			SoundEffect.MasterVolume = 1;

		}

		public void AddSoundInstance(SoundType soundType, string soundName)
		{
			if (sounds.ContainsKey(soundType))
			{
				throw new InvalidOperationException(string.Format("Sound '{0}' has already been loaded", soundType));
			}

			sounds.Add(soundType, _content.Load<SoundEffect>(soundName));

		}

		/// <summary>
		/// Plays the instance of the sound... If already playing, does not play again.
		/// </summary>
		/// <param name="soundType"></param>
		public void PlaySound(SoundType soundType)
		{
			if(DoesSoundExist(soundType))
				soundInst[soundType].Play();
		}

		public void PlaySound(SoundType soundType, bool multipleInstance)
		{
			if (multipleInstance && DoesSoundExist(soundType))
				sounds[soundType].CreateInstance().Play();
			else
				soundInst[soundType].Play();
		}

		public void PlaySound(SoundType soundType, PlayerIndex indx)
		{
			playerSounds[indx][soundType].Play();
		}
		public void StopSound(SoundType soundType)
		{
			if(soundInst[soundType].State != SoundState.Stopped)
				soundInst[soundType].Stop();
		}

		public void PauseSound(SoundType soundType)
		{
			if (soundInst[soundType].State != SoundState.Stopped)
				soundInst[soundType].Pause();
		}

		public void PauseSound(SoundType soundType, PlayerIndex indx)
		{
			if (playerSounds[indx][soundType].State != SoundState.Stopped)
				soundInst[soundType].Pause();
		}

		public bool IsPlaying(SoundType soundType)
		{
			if (soundInst[soundType].State == SoundState.Playing)
				return true;
			else
				return false;
		}

		private bool DoesSoundExist(SoundType soundType)
		{
			return sounds.ContainsKey(soundType);
		}
	}
}
